#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

#define RUNNING 1

// #define DEBUG

void md5sum(const char *file_path, char *md5_file);
const char *GetTime();
int CheckFileExists(const char *file_path);
int CheckWritePermission(const char *file_path);
void help();
void version();

int main (int argc, char *argv[])
{
  if (argc < 2)
  {
    help();
    return EXIT_FAILURE;
  }

  char command[50];
  strcpy(command, argv[1]);
  
  if (strcmp(command, "--help") == 0)
  {
    help();
    return EXIT_SUCCESS;
  }
  else if (strcmp(command, "--version") == 0)
  {
    version();
    return EXIT_SUCCESS;
  }

  char subcommand[50];
  if (argv[2])
    strcpy(subcommand, argv[2]);

  if (argc < 3)
  {
    help();
    return EXIT_FAILURE;
  }
  
  const char *file_sorg = command;
  const char *file_dest = subcommand;
  
  char md5_file_sorg[256];
  char md5_file_dest[256];
  char copy_command[256];

  sprintf(copy_command, "cp %s %s", file_sorg, file_dest);

#ifdef DEBUG
  printf("copy_command: %s\n", copy_command);
#endif

  while (RUNNING)
  {
    if (CheckFileExists(file_sorg) == -1 || CheckFileExists(file_dest) == -1)
    {
      if (CheckFileExists(file_sorg) == -1)
	printf("[Error]: File '%s' not found.\n", file_sorg);

      if (CheckFileExists(file_dest) == -1)
	printf("[Error]: File '%s' not found.\n", file_dest);

      return EXIT_FAILURE;
    }

    if (CheckWritePermission(file_dest) == -1)
    {
      printf("[Error]: Cannot write to '%s'.\n", file_dest);
      return EXIT_FAILURE;
    }

    md5sum(file_sorg, md5_file_sorg);
    md5sum(file_dest, md5_file_dest);

    if (md5_file_sorg == NULL || md5_file_dest == NULL)
    {
      printf("[Error]: While running md5sum.\n");
      return EXIT_FAILURE;
    }

#ifdef DEBUG
    printf("md5sum file_sorg: %s.\n", md5_file_sorg);
    printf("md5sum file_dest: %s.\n", md5_file_dest);
#endif

    if (strcmp(md5_file_sorg, md5_file_dest) != 0) // Se i due md5sum non coincidono
    {
      printf("[%s] - Syncing '%s' -> '%s'.\n", GetTime(), file_sorg, file_dest);
      system(copy_command);
    }
    sleep(1);
  }
    
  return EXIT_SUCCESS;
}

void md5sum(const char *file_path, char *md5_file)
{
  FILE *cmd;
  char md5sum_command[256];

  sprintf(md5sum_command, "md5sum %s", file_path);
  cmd = popen(md5sum_command, "r");  
  if (cmd != NULL)
  {
    fgets(md5_file, sizeof(md5_file), cmd);
    strtok(md5_file, " ");
  }
  else
    md5_file = NULL;
   
  pclose(cmd);
}

const char *GetTime()
{
  static char time[30] = {' '};
  FILE *tm = popen("date +%H:%M:%S", "r");

  fgets(time, sizeof(time), tm);
  time[strlen(time)-1] = '\0';
  pclose(tm);
  
  return time;
}

int CheckFileExists(const char *file_path)
{
  if (access(file_path, R_OK) == 0)
    return 0;
  else
    return -1;
}

int CheckWritePermission(const char *file_path)
{
  if (access(file_path, W_OK) == 0)
    return 0;
  else
    return -1;
}

void help()
{
  printf("Usage: syncfile <source_file> <destination_file>\n");
}

void version()
{
  printf("Syncfile version 1.0\n");
  printf("Copyright (C) 2019 Andrea <andrea@gnu.org>\n");
  printf("License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>\n");
  printf("This is free software: you are free to change and redistribute it.\n");
  printf("There is NO WARRANTY, to the extent permitted by law.\n");
}

